package com.lsh.oms.mis.service.es;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.lsh.oms.api.service.es.EsAsyncInterface;
import com.lsh.oms.core.constant.LoggerConstant;
import com.lsh.oms.core.enums.EsOperateType;
import com.lsh.oms.core.enums.EsType;
import com.lsh.oms.core.service.es.EsOperateService;
import com.lsh.oms.core.utils.LoggerUtils;
import com.lsh.oms.mis.service.base.EsService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * ElasticSearch Async Service
 *
 * @author panxudong
 * @date 16/8/26
 */
@Service(protocol = "dubbo",async = true)
public class EsAsyncService implements EsAsyncInterface {

    @Autowired
    private EsService esService;

    @Autowired
    private EsOperateService esOperateService;

    @Override
    public <T> void batchCreateIndex(List<T> orderList) {
        this.batchSaveOrUpdate(orderList, true, EsType.BATCH_CREATE);
    }

    @Override
    public <T> void batchEditIndex(List<T> orderList) {
        this.batchSaveOrUpdate(orderList, false, EsType.BATCH_EDIT);
    }

    @Override
    public <T> void createIndex(T order) {
        this.saveOrUpdate(order, true, EsType.CREATE);
    }

    @Override
    public <T> void editIndex(T order) {
        this.saveOrUpdate(order, false, EsType.EDIT);
    }

    @Override
    public <T> void deleteIndex(T order) {
        String uuid = UUID.randomUUID().toString();
        EsType esType = EsType.DELETE;
        String operateType = esType.getDesc();

        LoggerUtils.saveLog(" [" + operateType + " index start][" + uuid +
                "][Params : " + JSON.toJSONString(order) + "]", LoggerConstant.LOGGER_INFO);

        Map<String, Object> errorMap;
        try {
            errorMap = esService.deleteIndex(order, uuid, operateType);
        } catch (Exception e) {
            LoggerUtils.saveLog(" [" + operateType + " index error][" + uuid + "][Error message : " + e.getMessage() + "]",
                    LoggerConstant.LOGGER_ERROR);
            return;
        }
        if(errorMap != null) {
            LoggerUtils.saveLog(" [" + operateType + " index][" + uuid + "][Delete failed!] " + JSON.toJSONString(errorMap), LoggerConstant.LOGGER_ERROR);
        }

        LoggerUtils.saveLog(" [" + operateType + " index end][" + uuid + "]", LoggerConstant.LOGGER_INFO);
    }

    private <T> void batchSaveOrUpdate(List<T> orderList, boolean isCreate, EsType esType) {
        String uuid = UUID.randomUUID().toString();
        String operateType = esType.getDesc();

        LoggerUtils.saveLog(" [" + operateType + " index start][" + uuid + "]", LoggerConstant.LOGGER_INFO);

        Map<String, Map<String, Object>> errorMap;
        try {
            errorMap = esService.batchSaveOrUpdate(orderList, isCreate, uuid, operateType);
        } catch (Exception e) {
            LoggerUtils.saveLog(" [" + operateType + " index error][" + uuid + "][Error message : " + e.getMessage() + "]",
                    LoggerConstant.LOGGER_ERROR);
            return;
        }

        if(errorMap != null && errorMap.size() > 0) {
            for(Map.Entry<String, Map<String, Object>> entry : errorMap.entrySet()) {
                String key = entry.getKey();
                Map<String, Object> map = entry.getValue();

                LoggerUtils.saveLog(" [" + operateType + " index][" + uuid + "][Insert into order_es_operate]" +
                        "[Key:" + key + "]", LoggerConstant.LOGGER_INFO);
                Integer count = esOperateService.insert(isCreate?EsOperateType.INSERT.getIndex():EsOperateType.UPDATE.getIndex(), map);
                if(count <= 0) {
                    LoggerUtils.saveLog(" [" + operateType + " index][" + uuid + "][Insert into order_es_operate fail][Key:" + key + "]"
                            , LoggerConstant.LOGGER_ERROR);
                }
            }
        }

        LoggerUtils.saveLog(" [" + operateType + " index end][" + uuid + "]", LoggerConstant.LOGGER_INFO);
    }

    private <T> void saveOrUpdate(T order, boolean isCreate, EsType esType) {
        String uuid = UUID.randomUUID().toString();
        String operateType = esType.getDesc();

        LoggerUtils.saveLog(" [" + operateType + " index start][" + uuid +
                "][Params : " + JSON.toJSONString(order) + "]", LoggerConstant.LOGGER_INFO);

        Map<String, Object> errorMap;
        try {
            errorMap = esService.saveOrUpdate(order, isCreate, uuid, operateType);
        } catch (Exception e) {
            LoggerUtils.saveLog(" [" + operateType + " index error][" + uuid + "][Error message : " + e.getMessage() + "]",
                    LoggerConstant.LOGGER_ERROR);
            return;
        }

        if(errorMap != null) {
            LoggerUtils.saveLog(" [" + operateType + " index][" + uuid + "][Insert into order_es_operate]", LoggerConstant.LOGGER_INFO);
            Integer count = esOperateService.insert(isCreate ? EsOperateType.INSERT.getIndex() : EsOperateType.UPDATE.getIndex(), errorMap);
            if(count <= 0) {
                LoggerUtils.saveLog(" [" + operateType + " index][" + uuid + "][Insert into order_es_operate fail]"
                        , LoggerConstant.LOGGER_ERROR);
            }
        }

        LoggerUtils.saveLog(" [" + operateType + " index end][" + uuid + "]", LoggerConstant.LOGGER_INFO);
    }

}
